home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*_______________________________________________________________________
- |
- | haeberlifont.c - support for polygonal fonts
- |
- | This is for 99% created by using cut & paste from files from Paul
- | Haeberli. Originally the support was for much more then is in this
- | file. I only needed the routines for polygonal fonts. Prototypes
- | were added.
- |
- | Frans van Hoesel, Xtreme Graphics Software
- |
- */
-
-
-
- /*
- * Copyright (C) 1991, Silicon Graphics, Inc.
- * All Rights Reserved.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <gl/gl.h>
- #include <bstring.h>
-
- #include "haeberlifont.h"
-
- #define OFMAGIC 0x93339333
-
- #define TM_TYPE 1
- #define PO_TYPE 2
- #define SP_TYPE 3
-
- /* ops for poly characters */
-
- #define PO_BGNLOOP (1)
- #define PO_ENDBGNLOOP (2)
- #define PO_RETENDLOOP (3)
- #define PO_RET (4)
-
- static void drawglyph(glyph *g);
- static void out_scanline(int y);
- static void out_span(int xmin, int xmax);
- static void execcharprog(short *sptr, int xmin, int ymin, float cscale);
- static Edge *newedge(void);
- static void freeedge( Edge *e );
- static void do_beginfacet(void);
- static void do_endfacet(void);
- static void do_vertex(float x, float y);
- static void createedge(Edge *e1, Edge *e2);
- static void myremoveoldspans(float y);
- static int chartoindex(objfnt *fnt, int c);
- static void createglyph(chardesc *cd, glyph *g);
- static void do_beginscan(int ylines);
- static void do_endscan(void);
- static void bmfree(Bitmap *b);
- static Bitmap *bmnew(int xsize, int ysize);
- static int bmrasbytes(Bitmap *b);
- static void bmpos(float xpos, float ypos);
- static void mydrawbitmap(Bitmap *bm);
-
- #define CDEL (30)
- #define MALLOCBYTES (200000)
-
- static unsigned char *thecountmap;
- static unsigned char *bmbase;
- static int xpix, ypix;
- static float cscale, curxpos, curypos;
- static unsigned long maptab[65];
- static unsigned long map3[65];
- static glyph *glyphcache;
- static long c1 = 0x0000FFFF;
- static long c2 = 0x000000FF;
-
- void charsetcolors(long col1, long col2) {
- c1 = col1;
- c2 = col2;
- }
-
- unsigned char *mymalloc(int n) {
- unsigned char *cptr;
-
- cptr = (unsigned char *)malloc(n);
- if(!cptr) {
- fprintf(stderr,"malloc can't get %d bytes\n",n);
- exit(1);
- }
- return cptr;
- }
-
-
- void glyphinit(objfnt *fnt) {
- int i, c, m3;
-
- glyphcache = (glyph *)mymalloc(fnt->nchars*sizeof(glyph));
- bzero(glyphcache,fnt->nchars*sizeof(glyph));
- thecountmap = (unsigned char *)mymalloc(MALLOCBYTES);
- for(i=0; i<=64; i++) {
- c = 255-(i*355)/64;
- if(c<(85-CDEL)) {
- c = 0;
- m3 = 2;
- } else if(c>(170+CDEL)) {
- c = 255;
- m3 = 0;
- } else {
- c = 128;
- m3 = 1;
- }
- maptab[i] = 0x10101*c;
- map3[i] = m3;
- }
- }
-
- void get_charpos(float *x, float *y) {
- *x = curxpos;
- *y = curypos;
- }
-
- void aafontmoveto(float xpos, float ypos) {
- curxpos = xpos;
- curypos = ypos;
- }
-
- void aafontsetsize(objfnt *fnt, float pixhigh) {
- cscale = (8.0*pixhigh)/fnt->scale;
- }
-
-
- void drawaafntchar(objfnt *fnt, int c) {
- int index;
- chardesc *cd;
- glyph *g;
-
- if(!glyphcache)
- glyphinit(fnt);
- index = chartoindex(fnt,c);
- if(index>=0) {
- g = glyphcache+index;
- if(g->cscale != cscale) {
- cd = fnt->chars+index;
- createglyph(cd,g);
- }
- drawglyph(g);
- }
- }
-
- static void createglyph(chardesc *cd, glyph *g) {
- int xmin, ymin;
- int xorg, yorg;
- int x, y;
- int xsize, ysize;
- unsigned char *cptr;
- short *sptr0;
- short *sptr1;
- unsigned short sbit;
-
- if(cd->data) {
- xmin = cscale*cd->llx;
- ymin = cscale*cd->lly;
- xmin = ((xmin+8000)&0xfffff8)-8000;
- ymin = ((ymin+8000)&0xfffff8)-8000;
- xorg = -xmin/8;
- yorg = -ymin/8;
- xsize = 8+(cscale*(cd->urx-cd->llx+1));
- ysize = 8+(cscale*(cd->ury-cd->lly+1));
- xpix = ((xsize-1)/8)+1;
- ypix = ((ysize-1)/8)+1;
- if((xpix*(ypix+1))>MALLOCBYTES) {
- fprintf(stderr,"increase MALLOCBYTES\n");
- exit(1);
- }
- bzero(thecountmap,xpix*ypix);
- do_beginscan(ysize);
- execcharprog(cd->data,xmin,ymin,cscale);
- do_endscan();
- } else {
- xpix = 0;
- ypix = 0;
- xorg = 0;
- yorg = 0;
- }
- if(g->bm0) {
- bmfree(g->bm0);
- g->bm0 = 0;
- bmfree(g->bm1);
- g->bm1 = 0;
- }
- g->movex = (cd->movex*cscale)/8.0;
- g->cscale = cscale;
- if(xpix>0 && ypix>0) {
- g->bm0 = bmnew(xpix,ypix);
- g->bm0->xorig = xorg;
- g->bm0->yorig = yorg;
- g->bm1 = bmnew(xpix,ypix);
- g->bm1->xorig = xorg;
- g->bm1->yorig = yorg;
- cptr = thecountmap;
- for(y=0; y<ypix; y++) {
- sptr0 = g->bm0->base+y*g->bm0->sper;
- sptr1 = g->bm1->base+y*g->bm1->sper;
- sbit = 0x8000;
- for(x=0; x<xpix; x++) {
- switch(map3[*cptr++]) {
- case 1:
- *sptr0 |= sbit;
- break;
- case 2:
- *sptr1 |= sbit;
- break;
- }
- sbit = (sbit>>1);
- if(!sbit) {
- sbit = 0x8000;
- sptr0++;
- sptr1++;
- }
- }
- }
- }
- }
-
- static void drawglyph(glyph *g) {
-
- if(g->bm0) {
- bmpos(curxpos,curypos);
- cpack(c1);
- mydrawbitmap(g->bm0);
- cpack(c2);
- mydrawbitmap(g->bm1);
- }
- curxpos += g->movex;
- curypos += g->movey;
- }
-
- static void out_scanline(int y) {
- bmbase = thecountmap+((y/8)*xpix);
- }
-
- static void out_span(int xmin, int xmax) {
- int x, x8, pxmin, pxmax;
- int count;
- unsigned char *cptr;
-
- pxmin = xmin>>3;
- pxmax = xmax>>3;
- x8 = pxmin<<3;
- cptr = bmbase+pxmin;
- for(x=pxmin; x<=pxmax; x++) {
- if(xmin<=x8)
- count = 8;
- else
- count = 8-xmin+x8;
- if(xmax<(x8+7))
- count -= ((x8+7)-xmax);
- *cptr += count;
- x8 += 8;
- cptr++;
- }
- }
-
- static void execcharprog(short *sptr, int xmin, int ymin, float c_scale) {
- int nverts;
- float fx, fy;
-
- while(1) {
- switch(*sptr++) {
- case PO_BGNLOOP:
- do_beginfacet();
- break;
- case PO_ENDBGNLOOP:
- do_endfacet();
- do_beginfacet();
- break;
- case PO_RETENDLOOP:
- do_endfacet();
- return;
- case PO_RET:
- return;
- }
- nverts = *sptr++;
- while(nverts--) {
- fx = c_scale*(sptr[0])-xmin;
- fy = c_scale*(sptr[1])-ymin;
- do_vertex(fx,fy);
- sptr+=2;
- }
- }
- }
-
- static float bmxpos, bmypos;
-
- static void mydrawbitmap(Bitmap *bm) {
- int ixpos, iypos, scanx;
- int x, y, sper, ysize;
- short *sptr;
-
- ixpos = bmxpos-bm->xorig;
- iypos = bmypos-bm->yorig;
- ysize = bm->ysize;
- sper = bm->sper;
- linewidth(1);
- sptr = bm->base;
- for(y=0; y<ysize; y++) {
- scanx = ixpos;
- for(x=0; x<sper; x++) {
- if(*sptr) {
- deflinestyle(1,*sptr++);
- setlinestyle(1);
- move2i(scanx+15,iypos);
- draw2i(scanx,iypos);
- } else
- sptr++;
- scanx+=16;
- }
- iypos++;
- }
- setlinestyle(0);
- }
-
- static void bmpos(float xpos, float ypos) {
- bmxpos = xpos;
- bmypos = ypos;
- cmov2(xpos,ypos);
- }
-
- #define NBUCKETS 20
- #define TOLERANCE 0.0000001
- #define NINCHUNK 40
-
- static Edge *edges, *active, *fedges;
- static Edge *buckets[NBUCKETS];
- static int npoints;
- static Edge start, current, last;
- static int scrymax;
-
- static Edge *newedge(void) {
- register Edge *e;
- register int i;
-
- if(!fedges) {
- e = (Edge *)mymalloc(NINCHUNK*sizeof(Edge));
- for(i=0; i<NINCHUNK; i++)
- freeedge(e++);
- }
- e = fedges;
- fedges = fedges->next;
- return e;
- }
-
- static void freeedge( Edge *e ) {
- if( e ) {
- e->next = fedges;
- fedges = e;
- }
- }
-
- static void do_beginfacet(void) {
- npoints = 0;
- }
-
- static void do_endfacet(void) {
- if(npoints>0)
- createedge(&last,&start);
- }
-
- static void do_vertex(float x, float y) {
- if(npoints++ == 0) {
- start = current;
- start.x = x;
- start.y = y;
- last = start;
- } else {
- current.x = x;
- current.y = y;
- createedge(&last,¤t);
- last = current;
- }
- }
-
- static void createedge(Edge *e1, Edge *e2) {
- register Edge *top, *bot;
- register Edge *e, *b;
- int bucketno;
- register float ystart;
- register float dy, ady;
-
- if(e1->y>e2->y) {
- top = e1;
- bot = e2;
- } else {
- top = e2;
- bot = e1;
- }
- ady = dy = top->y-bot->y;
- if(ady<0.0)
- ady = 0.0;
- if(ady < TOLERANCE)
- return;
- if(top->y<=0 || bot->y>=scrymax)
- return;
- e = newedge();
- e->ymax = top->y;
- e->ymin = bot->y;
- e->dxdy = (top->x-bot->x)/dy;
- e->x = bot->x;
- bucketno = (bot->y)*NBUCKETS/scrymax;
- if(bucketno<0) bucketno = 0;
- if(bucketno>=NBUCKETS) bucketno = NBUCKETS-1;
- b = (Edge *)&buckets[bucketno];
- ystart = e->ymin;
- while(b->next && (ystart > b->next->ymin))
- b = b->next;
- e->next = b->next;
- b->next = e;
- }
-
- static void do_beginscan(int ylines) {
- int i;
-
- scrymax = ylines;
- edges = NULL;
- active = NULL;
- for(i=0; i<NBUCKETS; i++)
- buckets[i] = NULL;
- }
-
- static void do_endscan(void) {
- Edge *llast, *span, *temp, *newspan;
- int i, iy, xchg, x1, x2;
- float y;
-
- edges = NULL;
- llast = (Edge *)&edges;
- for(i=0; i<NBUCKETS; i++) {
- if( (span=buckets[i]) != NULL ) {
- llast->next = span;
- while(span->next)
- span = span->next;
- llast = span;
- }
- }
- for(iy=0; iy<scrymax; iy++) {
- y = iy;
-
- /* remove old spans */
- myremoveoldspans(y);
-
- /* add new spans */
- temp = edges;
- while(temp && (temp->ymin <= y)) {
- newspan = temp;
- temp = temp->next;
- if(newspan->ymax > y) {
- newspan->x -= newspan->dxdy * (newspan->ymin - y);
- span = (Edge *)&active;
- while(span->next && (span->next->x < newspan->x) )
- span = span->next;
- newspan->next = span->next;
- span->next = newspan;
- }
- }
- edges = temp;
-
- /* order spans */
- if(active) {
- do {
- xchg = 0;
- span = (Edge *)&active;
- while(span->next && span->next->next) {
- while(span->next->next ) {
- if (span->next->x > span->next->next->x) {
- temp = span->next;
- span->next = temp->next;
- temp->next = temp->next->next;
- span->next->next = temp;
- xchg++;
- }
- span=span->next;
- }
- span=span->next;
- }
- } while( xchg );
-
- /* fill spans */
- out_scanline(iy);
- for(span=active; span && span->next; span=span->next->next) {
- x1 = span->x; x2 = span->next->x;
- out_span(x1,x2);
- }
-
- /* increment spans */
- for( span = active; span; span = span->next )
- span->x += (span->dxdy);
- }
- }
- while(active) {
- temp = active;
- active = active->next;
- freeedge(temp);
- }
- while(edges) {
- temp = edges;
- edges = edges->next;
- freeedge(temp);
- }
- }
-
- static void myremoveoldspans(float y) {
- register Edge *span, *temp;
-
- for( span = (Edge *)&active; span->next; ) {
- if (span->next->ymax <= y) {
- temp = span->next;
- span->next = temp->next;
- freeedge(temp);
- } else
- span = span->next;
- }
- }
-
-
- static Bitmap *bmnew(int xsize, int ysize) {
- register Bitmap *b;
-
- b = (Bitmap *)mymalloc(sizeof(Bitmap));
- b->xsize = xsize;
- b->ysize = ysize;
- b->xorig = 0;
- b->yorig = 0;
- b->xmove = 0;
- b->ymove = 0;
- if(b->ysize>0 && b->ysize>0) {
- b->sper = 1+((b->xsize-1)>>4);
- b->base = (short *)mymalloc(bmrasbytes(b));
- bzero(b->base,bmrasbytes(b));
- } else {
- b->sper = 0;
- b->xsize = 0;
- }
- return b;
- }
-
- static void bmfree(Bitmap *b){
- if(b->base)
- free(b->base);
- free(b);
- }
-
-
- static int bmrasbytes(Bitmap *b) {
- return b->ysize*2*b->sper;
- }
-
- static int chartoindex(objfnt *fnt, int c) {
- if(c<fnt->charmin)
- return -1;
- if(c>fnt->charmax)
- return -1;
- return c-fnt->charmin;
- }
-
-
- objfnt *readobjfnt(char *name) {
- FILE *inf;
- objfnt *fnt;
- short *sptr;
- int i;
- long magic;
-
- inf = fopen(name,"r");
- if(!inf) {
- fprintf(stderr,"readobjfnt: can't open input file %s\n",name);
- return 0;
- }
- fread(&magic,sizeof(long),1,inf);
- if(magic != OFMAGIC) {
- fprintf(stderr,"readobjfnt: bad magic nuber\n");
- return 0;
- }
- fnt = (objfnt *)mymalloc(sizeof(objfnt));
- fread(fnt,sizeof(objfnt),1,inf);
- fnt->freeaddr = 0;
- fnt->chars = (chardesc *)mymalloc(fnt->nchars*sizeof(chardesc));
- fread(fnt->chars,fnt->nchars*sizeof(chardesc),1,inf);
- for(i=0; i<fnt->nchars; i++) {
- if(fnt->chars[i].datalen>0) {
- sptr = (short *)mymalloc(fnt->chars[i].datalen);
- fnt->chars[i].data = sptr;
- fread(sptr,fnt->chars[i].datalen,1,inf);
- } else {
- fnt->chars[i].data = 0;
- }
- }
- fclose(inf);
- return fnt;
- }
-
-